package model;

import javax.swing.event.EventListenerList;

import model.events.ScoreEvent;
import model.iview.IPlayer;
import model.listeners.ScoreListener;

/**
 * Cette classe représente un joueur de Scrabble, avec son nom, son score et ses
 * lettres.
 * 
 * @author Lucile Gramusset et Guillaume Poussel
 */
public class Player implements IPlayer {

    /**
     * Nom du joueur
     */
    private String name;

    /**
     * Score du joueur
     */
    private int score;

    /**
     * Rack des lettres du joueur
     */
    private Rack rack;

    /**
     * Détermine si le joueur a passé son dernier tour. Ceci permet de savoir si
     * tous les joueurs ont passé.
     */
    private boolean skipped;

    /**
     * <i>Listeners</i> du score de ce joueur.
     */
    private EventListenerList scoreListeners = new EventListenerList();

    /**
     * Construit un joueur en spécifiant son nom
     * 
     * @param name
     *            Nom du joueur
     */
    public Player(String name) {
        this.name = name;
        this.score = 0;
        this.rack = new Rack();
        skipped = false;
    }

    /**
     * Change le nom du joueur
     * 
     * @param name
     *            Nouveau nom du joeuur
     */
    public void setName(String name) {
        this.name = name;
    }

    /* (non-Javadoc)
     * @see model.IPlayer#getName()
     */
    /* (non-Javadoc)
     * @see model.IPlayer#getName()
     */
    public String getName() {
        return name;
    }

    /**
     * Incrémente le score d'un certain total. L'incrément peut être négatif
     * 
     * @param increment
     *            Incrément du score
     */
    public void incScore(int increment) {
        setScore(this.score + increment);
    }

    /**
     * Change le score du joueur et avertit les <i>listeners</i>
     * 
     * @param score
     *            Nouveau score du joueur
     */
    private void setScore(int score) {
        this.score = score;
        fireScoreListeners();
    }

    /* (non-Javadoc)
     * @see model.IPlayer#getScore()
     */
    /* (non-Javadoc)
     * @see model.IPlayer#getScore()
     */
    public int getScore() {
        return score;
    }

    /* (non-Javadoc)
     * @see model.IPlayer#getRack()
     */
    /* (non-Javadoc)
     * @see model.IPlayer#getRack()
     */
    public Rack getRack() {
        return rack;
    }

    /* (non-Javadoc)
     * @see model.IPlayer#hasSkip()
     */
    public boolean hasSkip() {
        return skipped;
    }

    /**
     * Change l'état du joueur
     * 
     * @param skipped
     *            <code>true</code> si le joueur a passé son dernier tour,
     *            <code>false</code> sinon.
     */
    public void setSkipped(boolean skipped) {
        this.skipped = skipped;
    }

    /**
     * Termine le jeu en retranchant le score des lettres restantes au score du
     * joueur.
     * 
     * @return La somme des points des tuiles restants sur le rack
     */
    public int endGame() {
        this.incScore(-this.rack.getTotalScore());
        return this.rack.getTotalScore();
    }

    public String toString() {
        return "Player '" + this.getName() + "', with points :"
                + this.getScore() + " and rack " + this.getRack();
    }

    /**
     * Avertit les <i>listeners</i> de ce joueur.
     */
    private void fireScoreListeners() {
        ScoreEvent pe = new ScoreEvent(this, score);
        for (ScoreListener pl : scoreListeners
                .getListeners(ScoreListener.class)) {
            pl.scoreChanged(pe);
        }
    }

    /**
     * Ajoute un <i>listener</i> à ce joueur
     * 
     * @param scoreListener
     *            Le <i>listener</i>
     */
    public void addScoreListener(ScoreListener scoreListener) {
        this.scoreListeners.add(ScoreListener.class, scoreListener);
    }

    /**
     * Supprime un <i>listener</i> à ce joueur
     * 
     * @param scoreListener
     *            Le <i>listener</i> à supprimer
     */
    public void removeScoreListener(ScoreListener scoreListener) {
        this.scoreListeners.remove(ScoreListener.class, scoreListener);
    }

}
